#include "flash.h"
#include "machine_stat.h"
#include "IAP_Option_EW.h"
#include "string.h"
#include "open_power_code.h"
#include "buzzer.h"
#include "protocal.h"

Time flash_time;
static uint8_t ParamSm = 0;
static uint8_t bNewDevice = 1;  
unsigned char code* POINT = 0x00;

uint8_t flash_buzzer_stat;
uint8_t flash_running_mode;
uint16_t flash_mode_save_temp[3]; 
CycleOrder_t flash_CycleOrder;
uint16_t flash_CycleDuration;
uint8_t old_open_power_success;

void SyncParam(void);
/**************************************************
*�������ƣ�unsigned char IAP_Read(unsigned long IAP_IapAddr, unsigned char area)
*�������ܣ���Byte��ȡ
*��ڲ�����?
IAP_IapAddr:��Ҫ�����ĵ�ַ
area:��������,APROMΪ00,EEPROMΪ02
*���ڲ�����void
**************************************************/
unsigned char IAP_Read(unsigned long IAP_IapAddr, unsigned long area)
{
  unsigned char xdata IAP_IapData;
  //����IAPADE��EA
  unsigned char tempADER = IAPADE;
  bit temp = EA;

  EA = 0;             //�ر��ж�
  IAPADE = area;
  IAP_IapData = *(POINT + IAP_IapAddr);
	
  //���������ָ�IAPADE��EA������MOVCλ�ó���
  IAPADE = tempADER;
  EA = temp;
  return IAP_IapData;
}
uint8_t flash_read_data(uint8_t *pdata1,uint8_t pdata_len,uint16_t start_addr)
{
	uint8_t i=0;
	for(i=0;i<pdata_len;i++)
	{
		pdata1[i]=IAP_Read((start_addr+i),IAP_EEPROM);
	}
	return 1;
}
uint8_t flash_write_data(uint8_t *pdata1,uint8_t pdata_len,uint16_t start_addr)
{
	uint8_t i=0;
	IAP_EEPROMSectorEraseOption((start_addr));  
	for(i=0;i<pdata_len;i++)
	{
		IAP_EEPROMProgramByteOption((i+start_addr),pdata1[i]);
		//IAP_ProgramByte1((i+start_addr),pdata1[i],IAP_EEPROM);
	}
	return 1;
}

/** @brief 读取Flash中参数，并且校验合法性
 *  @retval 1-读取结果正确
 */
uint8_t Flash_Read(uint8_t *param, uint8_t size, uint16_t start_addr){
uint8_t buff[FLASH_PARAM_SIZE+2];    
uint8_t i=0;
uint8_t chksum; 
    
	for(i=0; i<size+2; i++)
		buff[i] = IAP_Read((start_addr+i), IAP_EEPROM);
    if(buff[0] != FLASH_STAT) return 0;
    chksum = checksum(buff, size+1); 
    if(chksum != buff[size+1]) return 0;
    for(i = 0; i < size; i++){
        param[i] = buff[1+i];
    }
	return 1;
}

/** @brief  将参数写入Flash中
 *  @retval 1-写入正确
 */
uint8_t Flash_Write(uint8_t *param, uint8_t size, uint16_t start_addr){
uint8_t wr_buff[FLASH_PARAM_SIZE+2];    
uint8_t rx_buff[FLASH_PARAM_SIZE+2]; 
uint8_t i=0;
uint8_t ret = 0; 
    wr_buff[0] = FLASH_STAT;
    for(i=0; i< size; i++)
        wr_buff[i+1] = param[i];
    wr_buff[size+1] = checksum(wr_buff, size+1);     

    for(i=0; i<FLASH_WRITE_TRY_TIMES; i++){
        flash_write_data(wr_buff, size+2, start_addr);
        flash_read_data(rx_buff, size+2, start_addr);
        if(memcmp(wr_buff, rx_buff, size+2)==0){
            ret = 1;
            break;
        }
    }
	return ret;
}

void DefaultCycleOrderParam(void){
    CycleOrder.Enable = 0x30;
    CycleOrder.TimeTable[0] = 0xDB;
    CycleOrder.TimeTable[1] = 0x22;
    CycleOrder.TimeTable[2] = 0x36;
    CycleDuration = 60; 
}

void LoadDefaultParam(void){
    buzzer_stat = BUZZER_ON;
    heater_info.running_mode = RUN_PLAIN;

    mode_save_temp[0] = DEF_PLAIN_TEMP;
    mode_save_temp[1] = DEF_KITCHEN_TEMP;
    mode_save_temp[2] = DEF_SHOWER_TEMP;

    DefaultCycleOrderParam();
}
void LoadParam(uint8_t *param){
    buzzer_stat = param[0];
    heater_info.running_mode = param[1];
    SetRunMode(heater_info.running_mode);
    /* 普通模式温度 2Bytes */
    mode_save_temp[0] = (param[2]<<8) + param[3];
    /* 厨房模式温度 2Bytes */
    mode_save_temp[1] = (param[4]<<8) + param[5];
    /* 淋浴模式温度 2Bytes */
    mode_save_temp[2] = (param[6]<<8) + param[7];
    CycleOrder.Enable = param[8];
    CycleOrder.TimeTable[0] = param[9];
    CycleOrder.TimeTable[1] = param[10];
    CycleOrder.TimeTable[2] = param[11];
    /* 循环启动T 2Bytes */
    CycleDuration = (param[12]<<8) + param[13];

    SyncParam();
}
/** @brief 将当前的参数保存起来用于比较参数是否修改 */
void SyncParam(void){
    flash_buzzer_stat = buzzer_stat;
    flash_running_mode =  heater_info.running_mode;
    flash_mode_save_temp[0] = mode_save_temp[0]; 
    flash_mode_save_temp[1] = mode_save_temp[1]; 
    flash_mode_save_temp[2] = mode_save_temp[2]; 
    flash_CycleOrder.Enable = CycleOrder.Enable;
    flash_CycleOrder.TimeTable[0] = CycleOrder.TimeTable[0];
    flash_CycleOrder.TimeTable[1] = CycleOrder.TimeTable[1];
    flash_CycleOrder.TimeTable[2] = CycleOrder.TimeTable[2];
    flash_CycleDuration = CycleDuration;
}

void SaveParam(void){
uint8_t wr_buff[FLASH_PARAM_SIZE];     
    wr_buff[0] = buzzer_stat;
    wr_buff[1] = heater_info.running_mode;
    /* 普通模式温度 2Bytes */
    wr_buff[2] = (mode_save_temp[0]>>8)&0xFF;
    wr_buff[3] = mode_save_temp[0]&0xFF;
    /* 厨房模式温度 2Bytes */
    wr_buff[4] = (mode_save_temp[1]>>8)&0xFF;
    wr_buff[5] = mode_save_temp[1]&0xFF;   
    /* 淋浴模式温度 2Bytes */
    wr_buff[6] = (mode_save_temp[2]>>8)&0xFF;
    wr_buff[7] = mode_save_temp[2]&0xFF;

    wr_buff[8] = CycleOrder.Enable;
    wr_buff[9] = CycleOrder.TimeTable[0];
    wr_buff[10] = CycleOrder.TimeTable[1];
    wr_buff[11] = CycleOrder.TimeTable[2];
    /* 循环启动T 2Bytes */
    wr_buff[12] = (CycleDuration>>8)&0xFF;
    wr_buff[13] = CycleDuration&0xFF;
    Flash_Write(wr_buff, FLASH_PARAM_SIZE, FLASH_PARAM_START_ADDR);
    SyncParam();
}

/** @brief 保存开机码成功标识 */
void SaveOpenPowerCode(void){
uint8_t wr_buff[1] = {OPEN_POWER_OK};     
    Flash_Write(wr_buff, 1, FLASH_OPENPOWER_START_ADDR);
}

uint8_t IsParamChange(void){
    if(flash_buzzer_stat != buzzer_stat) return 1;
    if(flash_running_mode !=  heater_info.running_mode) return 1;
    if(flash_mode_save_temp[0] != mode_save_temp[0]) return 1; 
    if(flash_mode_save_temp[1] != mode_save_temp[1]) return 1; 
    if(flash_mode_save_temp[2] != mode_save_temp[2]) return 1; 
    if(flash_CycleOrder.Enable != CycleOrder.Enable) return 1;
    if(flash_CycleOrder.TimeTable[0] != CycleOrder.TimeTable[0]) return 1;
    if(flash_CycleOrder.TimeTable[1] != CycleOrder.TimeTable[1]) return 1;
    if(flash_CycleOrder.TimeTable[2] != CycleOrder.TimeTable[2]) return 1;
    if(flash_CycleDuration != CycleDuration) return 1;
   return 0;
}

uint8_t zz=0;
void ParamTask_Init(void){
uint8_t i=0;
uint8_t rd_rslt;
uint8_t buff[FLASH_PARAM_SIZE]; 

    /* open power code */
    rd_rslt = Flash_Read(buff, 1, FLASH_OPENPOWER_START_ADDR);
    if(rd_rslt == 0) { 
       openpower_code.open_power_success = OPEN_POWER_NONE;
    }else
        openpower_code.open_power_success = (buff[0] == 1 ? OPEN_POWER_OK : OPEN_POWER_NONE);
    old_open_power_success = openpower_code.open_power_success;
    
    /* system parameter*/
    rd_rslt = Flash_Read(buff, FLASH_PARAM_SIZE, FLASH_PARAM_START_ADDR);
    if(rd_rslt == 0){
        LoadDefaultParam();
        bNewDevice = 1;
    } else{
        LoadParam(buff);
        bNewDevice = 0;
    }    
    Get_Time(TIME_CLEAN, &flash_time);
}

void ParamTask(void){
/* 参数保存 */    
    Get_Time(UnitHour, &flash_time);
    switch (ParamSm){
    case 0: 
        if(bNewDevice == 0)
            ParamSm = 1;
        else if(flash_time.time_hour >= PARAM_FIRST_SAVE_HOURS){
             SaveParam();
             Get_Time(TIME_CLEAN, &flash_time);
             bNewDevice = 0;
             ParamSm = 1;
        }
        break;
    case 1:
        if (flash_time.time_sec > 10) {
            if(IsParamChange())
                SaveParam();
           Get_Time(TIME_CLEAN, &flash_time);
        }
        break;
    default:
        break;
    }
/* 开机码成功保存  */ 
    if(old_open_power_success != OPEN_POWER_OK && openpower_code.open_power_success == OPEN_POWER_OK){
        SaveOpenPowerCode();
        old_open_power_success = OPEN_POWER_OK;
    }   
}

